﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using SPMS.Commons.Logging.Properties;
using SPMS.Commons.Logging;

namespace SPMS.Commons.Logging
{
    /// <summary>
    /// 将日志信息输出到控制台的日志类
    /// </summary>
    /// <remarks>用于将日志信息输出到控制台</remarks>
    /// <history>
    /// [zanezeng]               2009/9/18 11:47    创建
    /// </history>
    public sealed class ConsoleLog : AbstractLog
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="ConsoleLog"/>的新实例
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 13:57    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 14:26    创建
        /// </history>
        public ConsoleLog()
            : base()
        {
        }

        /// <summary>
        /// 初始化类型<see cref="ConsoleLog"/>的新实例
        /// </summary>
        /// <param name="level">关联到当期日志记录器上的日志级别</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 14:26    创建
        /// </history>
        public ConsoleLog( LogLevelEnum level )
            : base( level )
        {
        }

        #endregion

        #region ---Protected Method

        /// <summary>
        /// 输出日志信息
        /// </summary>
        /// <param name="level">要输出的日志信息的级别</param>
        /// <param name="ex">需要输出到日志的异常对象</param>
        /// <param name="message">需要输出到日志的信息</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 13:44    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 14:22    创建
        /// </history>
        protected override void WriteLogInternal( LogLevelEnum level, Exception ex, object message )
        {
            //用于保存格式化后的消息
            string formatedMessage = null;

            //获得调用帧
            StackFrame frame = GetLastStackFrame( TYPE_STACKBOUNDARY );

            //判断是否有调用堆栈
            if (null != frame)
            {
                //用于保存方法名称
                string methodName = "?";

                //用于保存类型名称
                string typeName = "?";

                //获得调用方法
                System.Reflection.MethodBase method = frame.GetMethod();

                //判断是否有方法信息
                if (null != method)
                {
                    //设置方法名称
                    methodName = method.Name;

                    //判断是否有声明类型
                    if (null != method.DeclaringType)
                    {
                        typeName = method.DeclaringType.FullName;
                    }
                }

                //格式化消息
                formatedMessage = string.Format( System.Globalization.CultureInfo.InvariantCulture, ": [{0:yyyy/MM/dd HH:mm:ss fff}] [{1}] [{2}::{3} {4}:{5}]", DateTime.Now, message, typeName, methodName, frame.GetFileName(), frame.GetFileLineNumber() );
            }
            else
            {
                //格式化消息
                formatedMessage = string.Format( System.Globalization.CultureInfo.InvariantCulture, ": [{0:yyyy/MM/dd HH:mm:ss fff}] [{1}]", DateTime.Now, message );
            }

            //获得日志级别的名称
            string levelName = GetLogLevelDisplayName( level );

            //获得日志信息的现实颜色
            ConsoleColor color = GetLogLevelReanderColor( level );

            //设置显示颜色
            Console.ForegroundColor = color;

            //输出日志级别名称
            Console.Write( levelName );

            //设置显示颜色
            Console.ForegroundColor = ConsoleColor.White;

            //输出格式化后的消息
            Console.WriteLine( formatedMessage );

            //判断是否有异常信息
            if (null != ex)
            {
                //输出分隔
                Console.WriteLine( "--------------------------------------------------------------------------------" );

                //输出异常信息
                Console.WriteLine( ex.ToString() );
            }

            //输出分隔
            Console.WriteLine( "--------------------------------------------------------------------------------" );
        }

        #endregion

        #region ---Private Method

        /// <summary>
        /// 获得不同日志级别信息的渲染颜色
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <returns>日志信息的显示颜色</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/18 11:59    创建
        /// </history>
        private ConsoleColor GetLogLevelReanderColor( LogLevelEnum level )
        {
            //获得日志级别的名称
            switch (level)
            {
                case LogLevelEnum.Debug:
                    //调试信息
                    return ConsoleColor.White;

                case LogLevelEnum.Trace:
                    //跟踪信息
                    return ConsoleColor.Green;

                case LogLevelEnum.Info:
                    //提示信息
                    return ConsoleColor.Cyan;

                case LogLevelEnum.Warn:
                    //警告信息
                    return ConsoleColor.Yellow;

                case LogLevelEnum.Error:
                    //错误信息
                    return ConsoleColor.Red;

                case LogLevelEnum.Fatal:
                    //灾难
                    return ConsoleColor.Magenta;

                default:
                    //默认
                    return ConsoleColor.White;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 调用堆栈分界类型
        /// </summary>
        private readonly static Type TYPE_STACKBOUNDARY = typeof( AbstractLog );

        #endregion
    }
}
